package cli

import (
	"compress/gzip"
	"encoding/json"
	"errors"
	"fmt"
	_ "gitee.com/hubdev/api/git/cli/add"
	_ "gitee.com/hubdev/api/git/cli/del"
	_ "gitee.com/hubdev/api/git/cli/get"
	_ "gitee.com/hubdev/api/git/cli/update"
	"gitee.com/hubdev/api/git/ops"
	v1 "gitee.com/hubdev/api/git/v1"
	"io"
	"io/ioutil"
	"net/http"
)

type CliContext struct {
	Url   string       `json:"url,omitempty"`
	Token string       `json:"token,omitempty"`
	Op    ops.Op       `json:"op,omitempty"`
	Res   *v1.Resource `json:"res,omitempty"`
	Body  []byte       `json:"body,omitempty"`
}

func (c *CliContext) RequestOf(op ops.Op, res *v1.Resource) (*http.Request, error) {
	if fn, ok := ops.OpFuncs[op]; ok {
		return fn(c.Url, c.Token, res)
	}
	return nil, errors.New(fmt.Sprintf("unknown op type: %d", op))
}

func (c *CliContext) Invoke(data interface{}) error {
	var req *http.Request
	var err error

	if req, err = c.RequestOf(c.Op, c.Res); err != nil {
		return err
	}

	var rsp *http.Response
	if rsp, err = http.DefaultClient.Do(req); err != nil {
		return err
	}
	defer rsp.Body.Close()
	c.unCoding(rsp)
	return json.Unmarshal(c.Body, data)
}
func (c *CliContext) unCoding(r *http.Response) {
	if r.StatusCode == 200 {
		switch r.Header.Get("Content-Encoding") {
		case "gzip":
			reader, _ := gzip.NewReader(r.Body)
			for {
				buf := make([]byte, 1024)
				n, err := reader.Read(buf)
				if err != nil && err != io.EOF {
					panic(err)
				}
				if n == 0 {
					break
				}
				c.Body =append(c.Body,buf[:n-1]...)
			}
		default:
			bodyByte, _ := ioutil.ReadAll(r.Body)
			c.Body = bodyByte
		}
	} else {
		bodyByte, _ := ioutil.ReadAll(r.Body)
		c.Body = bodyByte
	}
}
